package org.ruoyi.interview.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.ruoyi.common.core.utils.MapstructUtils;
import org.ruoyi.common.mybatis.core.page.PageQuery;
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
import org.ruoyi.interview.domain.InterviewQuestionCategory;
import org.ruoyi.interview.domain.bo.InterviewQuestionCategoryBo;
import org.ruoyi.interview.domain.vo.InterviewQuestionCategoryVo;
import org.ruoyi.interview.domain.vo.InterviewQuestionCategoryWithCountVo;
import org.ruoyi.interview.mapper.InterviewQuestionCategoryMapper;
import org.ruoyi.interview.service.IInterviewQuestionCategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;

import org.springframework.beans.factory.annotation.Value;

/**
 * 面试题分类Service业务层处理
 *
 * @author ruoyi
 */
@RequiredArgsConstructor
@Service
public class InterviewQuestionCategoryServiceImpl implements IInterviewQuestionCategoryService {

    private final InterviewQuestionCategoryMapper baseMapper;

    @Value("${dashscope.api.key:}")
    private String dashScopeApiKey;

    /**
     * 查询面试题分类
     *
     * @param categoryId 分类主键
     * @return 面试题分类
     */
    @Override
    public InterviewQuestionCategoryVo selectInterviewQuestionCategoryById(Long categoryId) {
        return baseMapper.selectVoById(categoryId);
    }

    /**
     * 查询面试题分类列表
     *
     * @param bo 面试题分类业务对象
     * @return 面试题分类集合
     */
    @Override
    public List<InterviewQuestionCategoryVo> selectInterviewQuestionCategoryList(InterviewQuestionCategoryBo bo) {
        LambdaQueryWrapper<InterviewQuestionCategory> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public TableDataInfo<InterviewQuestionCategoryWithCountVo> selectInterviewQuestionCategoryListWithCount(InterviewQuestionCategoryBo bo, PageQuery pageQuery) {
        IPage<InterviewQuestionCategoryWithCountVo> result = baseMapper.selectVoPageWithCount(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 查询面试题分类列表
     *
     * @param bo 面试题分类业务对象
     * @param pageQuery 分页参数
     * @return 面试题分类集合
     */
    @Override
    public TableDataInfo<InterviewQuestionCategoryVo> selectInterviewQuestionCategoryList(InterviewQuestionCategoryBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<InterviewQuestionCategory> lqw = buildQueryWrapper(bo);
        Page<InterviewQuestionCategoryVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 新增面试题分类
     *
     * @param bo 面试题分类业务对象
     * @return 结果
     */
    @Override
    public Boolean insertInterviewQuestionCategory(InterviewQuestionCategoryBo bo) {
        InterviewQuestionCategory add = MapstructUtils.convert(bo, InterviewQuestionCategory.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setCategoryId(add.getCategoryId());
        }
        return flag;
    }

    /**
     * 修改面试题分类
     *
     * @param bo 面试题分类业务对象
     * @return 结果
     */
    @Override
    public Boolean updateInterviewQuestionCategory(InterviewQuestionCategoryBo bo) {
        InterviewQuestionCategory update = MapstructUtils.convert(bo, InterviewQuestionCategory.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 批量修改面试题分类状态
     *
     * @param categoryId 分类主键
     * @param status 状态值
     * @return 结果
     */
    @Override
    public Boolean updateCategoryStatus(Long categoryId, String status) {
        LambdaUpdateWrapper<InterviewQuestionCategory> luw = new LambdaUpdateWrapper<>();
        luw.set(InterviewQuestionCategory::getStatus, status);
        luw.eq(InterviewQuestionCategory::getCategoryId, categoryId);
        return baseMapper.update(luw) > 0;
    }

    /**
     * 批量删除面试题分类
     *
     * @param categoryIds 需要删除的面试题分类主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteInterviewQuestionCategoryByIds(Collection<Long> categoryIds) {
        if (CollUtil.isEmpty(categoryIds)) {
            return false;
        }
        // 删除分类前需要判断是否存在子分类或关联的面试题
        for (Long categoryId : categoryIds) {
            // 检查是否存在子分类
            LambdaQueryWrapper<InterviewQuestionCategory> lqw = Wrappers.lambdaQuery();
            lqw.eq(InterviewQuestionCategory::getParentId, categoryId);
            if (baseMapper.selectCount(lqw) > 0) {
                throw new RuntimeException("分类存在子分类，无法删除");
            }

        }
        return baseMapper.deleteBatchIds(categoryIds) > 0;
    }

    /**
     * 批量更新分类排序
     *
     * @param categoryBoList 分类业务对象集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateOrderBatch(Collection<InterviewQuestionCategoryBo> categoryBoList) {
        if (CollUtil.isEmpty(categoryBoList)) {
            return false;
        }
        List<InterviewQuestionCategory> list = categoryBoList.stream()
            .map(bo -> {
                InterviewQuestionCategory category = new InterviewQuestionCategory();
                category.setCategoryId(bo.getCategoryId());
                category.setOrderNum(bo.getOrderNum());
                return category;
            })
            .collect(Collectors.toList());
        return baseMapper.updateBatchById(list);
    }

    /**
     * 构建查询对象
     *
     * @param bo 面试题分类业务对象
     * @return 查询对象
     */
    private LambdaQueryWrapper<InterviewQuestionCategory> buildQueryWrapper(InterviewQuestionCategoryBo bo) {
        LambdaQueryWrapper<InterviewQuestionCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getParentId() != null, InterviewQuestionCategory::getParentId, bo.getParentId());
        lqw.like(StringUtils.isNotBlank(bo.getCategoryName()), InterviewQuestionCategory::getCategoryName, bo.getCategoryName());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), InterviewQuestionCategory::getStatus, bo.getStatus());
        lqw.orderByAsc(InterviewQuestionCategory::getParentId);
        lqw.orderByAsc(InterviewQuestionCategory::getOrderNum);
        return lqw;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(InterviewQuestionCategory entity) {
        // TODO 根据业务逻辑添加校验
    }

    /**
     * 通过AI获取面试题分类
     *
     * @param parentId 父级分类ID
     * @param prompt 提示词
     * @return AI推荐的分类列表
     */
    @Override
    public List<String> getCategoryByAi(Long parentId, String prompt) throws Exception {
        // 1. 查询该父类下的所有子类目
        List<InterviewQuestionCategory> subCategories = baseMapper.selectListByParentId(parentId);
        List<String> subCategoryNames = subCategories.stream()
            .map(InterviewQuestionCategory::getCategoryName)
            .collect(Collectors.toList());

        // 2. 构建发送给AI的提示词
        StringBuilder promptBuilder = new StringBuilder();
        promptBuilder.append("当前已有子分类：");
        if (!subCategoryNames.isEmpty()) {
            promptBuilder.append(String.join("、", subCategoryNames));
        } else {
            promptBuilder.append("无");
        }
        promptBuilder.append("\n\n");
        promptBuilder.append("用户提示词：").append(prompt).append("\n\n");
        promptBuilder.append("请根据用户提示词和当前已有子分类，推荐更多相关的面试题子分类。");
        promptBuilder.append("只需要返回新增的子分类名称列表，每个分类名称占一行，不要返回其他内容。");
        promptBuilder.append("注意：不要重复返回已有的子分类。");

        String fullPrompt = promptBuilder.toString();

        // 3. 调用DashScope API发送请求
        if (StringUtils.isBlank(dashScopeApiKey)) {
            throw new Exception("DashScope API Key未配置");
        }

        Constants.apiKey = dashScopeApiKey;

        Generation gen = new Generation();
        Message userMessage = Message.builder()
            .role(Role.USER.getValue())
            .content(fullPrompt)
            .build();

        GenerationParam param = GenerationParam.builder()
            .model(Generation.Models.QWEN_MAX)
            .messages(Collections.singletonList(userMessage))
            .resultFormat(GenerationParam.ResultFormat.MESSAGE)
            .build();

        GenerationResult result = gen.call(param);

        // 4. 解析返回结果
        String aiResponse = result.getOutput().getChoices().get(0).getMessage().getContent();

        // 5. 处理AI返回的分类列表
        String[] lines = aiResponse.split("\n");
        List<String> aiCategoryNames = new ArrayList<>();
        for (String line : lines) {
            String trimmedLine = line.trim();
            if (!trimmedLine.isEmpty() && !subCategoryNames.contains(trimmedLine)) {
                aiCategoryNames.add(trimmedLine);
            }
        }

        return aiCategoryNames;
    }
}
